from typing import Any, Dict, TextIO, List, Literal, Optional
from typing_extensions import Annotated
from json import load
from numpy import array, int16, lexsort, in1d, argsort
from numpy.typing import NDArray
from config import get_settings
import os

"""
    1. serach name index by name
    2. use name index find reference point
    3. use reference point's actual_point_index find actual point
"""

# class SwdGraphsDict(TypedDict):
#     Tracks: dict
#     Points: dict
#     Special_Cases: dict

class CoordinatesParser:
    def __init__(self) -> None:
        settings = get_settings()

        self.swd_coordinates_json_file: Optional[TextIO] = None

        self.names: List[str] = []


        self.actual_coordinates: Optional[List[Any | List[int]] ] = []

        self.reference_coordinates: Optional[List[Any | List[int]]] = []

        self.index: int = 0
        self.type: int = 0
        self.coordinate_type: str
        self.coordinate_name: str

        self.extras: Optional[List[List[int]]] = []

        self.green_triangle_coordinates: dict = {}
        self.reversed_green_triangle_coordinates:dict = {}
        self.dummy_track_coordinates:dict = {}
        self.track_graphs:dict = {}
        self.points_graphs:dict = {}
        self.special_cases:dict = {}
        
        # 配置文件路及
        self.track_graph_file = os.path.join(settings.BASE_DIR, "config", "track_graph.json")
        self.coordinates_file = os.path.join(settings.BASE_DIR, "config", "coordinates.json")

        ### read
        self.read_track_graph_file()
        self.read_coordinates_file()
    
        #### end
        self.actual_points: NDArray[int16] = array(self.actual_coordinates, dtype=int16)
        reference_points: NDArray[int16] = array(self.reference_coordinates, dtype=int16)

        # sort x axis then y axis.
        self.reference_points: NDArray[int16] = \
            reference_points[
                lexsort((reference_points[:, 0, 1], reference_points[:, 0, 0]))
            ]

        self.actual_coordinates *= 0
        self.actual_coordinates = None

        self.reference_coordinates *= 0
        self.reference_coordinates = None


    def read_track_graph_file(self):
        with open(self.track_graph_file) as swd_graph_json_file:
            swd_graphs = load(swd_graph_json_file)
            self.track_graphs = swd_graphs["Tracks"]
            self.points_graphs = swd_graphs["Points"]
            self.special_cases = swd_graphs["Special_Cases"]

    def read_coordinates_file(self):
        with open(self.coordinates_file) as swd_coordinates_json_file:
            coordinate_type: Literal["Tracks", "Points"] 
            coordinate_name: Annotated[str,"路段名字"]
            swd_coordinates: Dict[str, Any] = load(swd_coordinates_json_file) # 全部数据

            for coordinate_type in swd_coordinates:
                for coordinate_name in swd_coordinates[coordinate_type]:
                    self.type = 0
                    self.extras *= 0

                    swd_coordinate_data: Annotated[Dict[str, Any], "路段名对应的value"] = \
                        swd_coordinates[coordinate_type][coordinate_name]

                    reference_coordinate: Annotated[List[int], "路段的坐标点"] = swd_coordinate_data["Track_Area"]
                    if coordinate_type == "Tracks":
                        if "Dummy_Points" in swd_coordinate_data:

                            if swd_coordinate_data["Dummy_Points"]:
                                [
                                    (
                                        self.reference_coordinates.append(
                                            [
                                                dummy_coordinate,
                                                [len(self.actual_coordinates), self.index]
                                            ]
                                        ),

                                        self.actual_coordinates.append(
                                            [
                                                [-1, -1],
                                                [-1, -1],
                                                [-1, -1],
                                                [-1, -1],
                                                [2, -1],
                                            ]
                                        )
                                    )

                                    for dummy_coordinate in
                                    swd_coordinate_data["Dummy_Points"]
                                ]


                        self.green_triangle_coordinates.update(
                            {
                                str(triangle_coordinate): coordinate_name

                                for triangle_coordinate in
                                swd_coordinate_data["Green_Triangles"]
                            }
                        )

                        self.reversed_green_triangle_coordinates.update(
                            {
                                str(direction_coordinate): coordinate_name

                                for direction_coordinate in
                                swd_coordinate_data["Directions"]
                            }
                        )



                    if reference_coordinate:
                        if reference_coordinate[0] == -1:
                            continue
                    else:
                        continue

                    self.reference_coordinates.append(
                        [
                            reference_coordinate,
                            [len(self.actual_coordinates), self.index]
                        ]
                    )

                    if coordinate_type == "Tracks":
                        self.type = 1

                    if "Color_Area" in swd_coordinate_data:
                        if isinstance(swd_coordinate_data["Color_Area"], Dict):
                            if "Normal" in swd_coordinate_data["Color_Area"] \
                                    and "Reverse" in swd_coordinate_data["Color_Area"]:

                                if swd_coordinate_data["Color_Area"]["Normal"] \
                                        and swd_coordinate_data["Color_Area"][
                                            "Reverse"]:

                                    self.actual_coordinates.append(
                                        [
                                            swd_coordinate_data["Color_Area"]
                                            ["Normal"][0],

                                            swd_coordinate_data["Color_Area"]
                                            ["Normal"][1],

                                            swd_coordinate_data["Color_Area"]
                                            ["Reverse"][0],

                                            swd_coordinate_data["Color_Area"]
                                            ["Reverse"][1],

                                            [self.type, -1],
                                        ]
                                    )
                    else:
                        self.actual_coordinates.append(
                            [
                                [-1, -1],
                                [-1, -1],
                                [-1, -1],
                                [-1, -1],
                                [self.type, -1],
                            ]
                        )


                    self.names.append(coordinate_name)

                    self.index += 1

coordinates_parser = CoordinatesParser()